/*
 * Funny Language - a free style programming language.
 * Copyright (C) 2015 by fanguangping (fanguangping@163.com)
 * hash.c
 */

#include <stdlib.h>
#include "hash.h"
#include "../base/cmemory.h"

HashTable alloc_hash_table() {
	return (HashTable) sys_malloc(HASHTABLE_SIZE * sizeof(HashNode *));
}

HashNode *alloc_hash_node() {
	return (HashNode *) sys_malloc(sizeof(HashNode));
}

HashTable init_table() {
	HashTable table = alloc_hash_table();
	int i;
	for (i = 0; i < HASHTABLE_SIZE; i++) {
		table[i] = NULL;
	}
	return table;
}

void put_table_element(HashTable table, void *key, void *value,
		int (*hash_code)(void *key)) {
	HashNode *valueNode = NULL;
	int hash = 0;
	HashNode *node = NULL;
	if (table == NULL || key == NULL || value == NULL || hash_code == NULL)
		return;

	valueNode = alloc_hash_node();
	valueNode->element = value;
	valueNode->next = NULL;
	hash = hash_code(key);
	node = table[hash];

	if (node == NULL) {
		table[hash] = valueNode;
	} else {
		while (node->next != NULL)
			node = node->next;
		node->next = valueNode;
	}
}

HashNode *get_table_element(HashTable table, void *key,
		int (*hash_code)(void *key)) {
	if (table == NULL || key == NULL || hash_code == NULL)
		return NULL;
	else
		return table[hash_code(key)];
}

void clear_table(HashTable table) {
	HashNode *node = NULL, *p = NULL;
	int i;
	if (table == NULL)
		return;

	for (i = 0; i < HASHTABLE_SIZE; i++) {
		p = table[i];
		while (p != NULL) {
			node = p;
			p = node->next;
			sys_free(node);
		}
		table[i] = NULL;
	}
}

int hash_code_string(void *key) {
    int hash = 0;
    char *p = key;
    while (*p++) {
        hash += *p;
    }
    hash = hash % HASHTABLE_SIZE;
    return hash;
}

